/**
 * 可显示对象基类
 * @author zzhanglin
 * @returns {DisplayObject}
 */
DisplayObject = function()
{
	EventDispatcher.call(this);
	
	this.className="DisplayObject"; //类名
	this.visible = true ; //是否可见
	this.name="";//名称
	
	//================================
	//私有属性
	this._localModelMatrix = new Matrix();
	this._worldModelMatrix = new Matrix();
	this._invalidateMatrix = true ;
	
	this._stage = null ; //只读
	this._rotation=0 ;//旋转的角度
	this._parent = null ; //父容器
	this._alpha = 1 ; //透明度
	
	this._mouseX = 0 ; //鼠标坐标
	this._mouseY = 0 ;
	
	this._scaleX = 1; //缩放
	this._scaleY = 1 ;
	
	this._width = 0 ; //宽高
	this._height = 0;
	
	this._x = 0 ; //位置
	this._y = 0 ;
	
	this._pivotX = 0 ; //注册点坐标
	this._pivotY =0 ;
	
	
	//用于像素碰撞检测使用的Context
	if( !DisplayObject._hitTestContext){
		 DisplayObject._hitTestContext = document.createElement("canvas").getContext("2d"); 
		 DisplayObject._hitTestContext.width = 1;
		 DisplayObject._hitTestContext.height = 1;
	}
};
FLASH.extend(DisplayObject,EventDispatcher); //继承自EventDispatcher

//================================================
//===================设置getter/setter====================

//stage
DisplayObject.prototype.getStage = function(){return this._stage ;};
//parent
DisplayObject.prototype.getParent = function(){return this._parent ;};
//mouseX
DisplayObject.prototype.getMouseX = function(){ return this._mouseX ; };
//mouseY
DisplayObject.prototype.getMouseY= function(){ return this._mouseY; };

//旋转
DisplayObject.prototype.getRotation= function(){ return this._rotation; };
DisplayObject.prototype.setRotation= function(value){ 
	if(this._rotation != value) {
		this._rotation = value;
		this._invalidateMatrix = true;
	} ;
};

//缩放
DisplayObject.prototype.getScaleX = function(){ return this._scaleX ;};
DisplayObject.prototype.setScaleX= function(value){ 
	if(this._scaleX!=value){
		this._invalidateMatrix = true;
		this._scaleX = value; 
	}
};
DisplayObject.prototype.getScaleY= function(){ return this._scaleY ;};
DisplayObject.prototype.setScaleY= function(value){ 
	if(this._scaleY!=value){
		this._scaleY = value; 
		this._invalidateMatrix = true;
	}
};

//宽高
DisplayObject.prototype.getWidth= function(){ return this._width*Math.abs(this._scaleX) ;};
DisplayObject.prototype.setWidth= function(value){
	this._width = value ;
	if(this._width>0){
		this._scaleX = value / this._width ;
	}else{
		this._scaleX = 1.0 ;
	}
};
DisplayObject.prototype.getHeight= function(){ return this._height*Math.abs(this._scaleY) ;};
DisplayObject.prototype.setHeight= function(value){ 
	this._height = value ;
	if(this._height>0){
		this._scaleY = value / this._height ;
	}else{
		this._scaleY = 1.0 ;
	}
};

//位置
DisplayObject.prototype.getX= function(){ return this._x ;};
DisplayObject.prototype.setX= function(value){ 
	if(this._x != value) {
		this._x = value;
		this._invalidateMatrix = true;
	};
};
DisplayObject.prototype.getY= function(){ return this._y ;};
DisplayObject.prototype.setY= function(value){ 
	if(this._y != value) {
		this._y = value;
		this._invalidateMatrix = true;
	};
};

//注册点坐标
DisplayObject.prototype.getPivotX= function(){ return this._pivotX ;};
DisplayObject.prototype.setPivotX = function(value){ 
	if(this._pivotX != value) {
		this._pivotX = value ;
		this._invalidateMatrix = true;
	};
};
DisplayObject.prototype.getPivotY= function(){ return this._pivotY ;};
DisplayObject.prototype.setPivotY = function(value){ 
	if(this._pivotY != value) {
		this._pivotY = value ;
		this._invalidateMatrix = true;
	};
};

//透明度
DisplayObject.prototype.getAlpha= function(){ return this._alpha;};
DisplayObject.prototype.setAlpha = function( value){
	if(this._alpha!=value)
		this._alpha = Math.max(0.0, Math.min(1.0, value)); 
};

/**====================================*/
/** 设置方法 */

/**
 * 返回一个矩形，该矩形定义相对于 targetCoordinateSpace 对象坐标系的显示对象区域
 * @param targetCoordinateSpace
 * @return 
 */
DisplayObject.prototype.getBounds = function(targetCoordinateSpace)
{
	var matrix = new Matrix() ;
	var currentTarget = this ;
	while( currentTarget && currentTarget!=targetCoordinateSpace ){
		matrix.concat( currentTarget._localModelMatrix );
		currentTarget  = currentTarget._parent ;
	}
    var position = matrix.transformPoint( 0 , 0 ) ;
    //旋转和缩放后真实的宽高
    var angle = this._rotation*Math.PI/180 ;	
    var rw = this.getWidth(); //宽度
    var rh = this.getHeight(); //高度
    var sa = Math.abs(Math.sin(angle)) ; //sin(angle)
    var ca = Math.abs(Math.cos(angle)) ; //cos(angle)
    var w = rw*ca + rh*sa ;
    var h =  rw*sa + rh*ca ;
	return new Rectangle(position.x , position.y , w>>0 , h>>0 ) ;
};

/**
 * 将注册点设置为中心
 */
DisplayObject.prototype.centerPivot = function()
{
	this.setPivotX(this.getWidth()/2);
	this.setPivotY(this.getHeight()/2);
};

/**
 * 将 point 对象从舞台（全局）坐标转换为显示对象的（本地）坐标。
 * @param point 用 Point 类创建的对象。该 Point 对象指定 x 和 y 坐标作为属性
 * @returns 具有相对于显示对象的坐标的 Point 对象
 */
DisplayObject.prototype.globalToLocal = function (point)
{
	 var transformationMatrix =  this._worldModelMatrix.clone();
	 transformationMatrix.inverse(); //倒置
	 return transformationMatrix.transformPoint( point.x , point.y );
};

/**
 * 将 point 对象从显示对象的（本地）坐标转换为舞台（全局）坐标。	
 * @param point 使用 Point 类创建的点的名称或标识符，指定 x 和 y 坐标作为属性
 * @returns 具有相对于舞台的坐标的 Point 对象。
 */
DisplayObject.prototype.localToGlobal = function(point)
{
    return this._worldModelMatrix.transformPoint( point.x , point.y );
};

/**
 * 计算显示对象，以确定它是否与 x 和 y 参数指定的点重叠或相交。
 * @param x
 * @param y
 * @param spaceIsStage 空间是否在stage , 为true时，x,y表示全局鼠标位置，为false时，表示当前对象上面的鼠标位置，默认为false
 * @returns 相交返回true，否则返回false
 */
DisplayObject.prototype.hitTestPoint = function( x , y , spaceIsStage )
{
	var space = spaceIsStage?FlashCore.stage:this ;
	//判断矩形是否包含此点
	 return this.getBounds(space).containsPoint( new Point(x,y));
};

/**
 * 像素碰撞检测点 ,如果图片没有绽放和旋转过，可以先使用矩形碰撞来排除，这样可以提高效率
 * <b>像素碰撞暂时只能在服务器上测试，本地可能无法测试，因为浏览器安全原因</b>
 * @param stageX 全局坐标X
 * @param stageY 全局坐标Y
 * @param minAlpha  最小的alpha值，默认为 255
 * @returns 成功返回true
 */
DisplayObject.prototype.hitTestPointPixels = function( stageX , stageY , minAlpha)
{
	minAlpha = minAlpha?minAlpha:255 ; 
	//像素精确检测
	var hitContext = this._getPixelsHitTestContext ();
	hitContext.canvas.width = FlashCore.canvas.width;
	hitContext.canvas.height = FlashCore.canvas.height;
	this._draw( this._alpha ,  hitContext );
	var result = false;
	try{
		var data = hitContext.getImageData( stageX , stageY , 1 ,1 ).data;
		if(data[3] >= minAlpha) result = true;
		
	}catch(e){  }
	hitContext.canvas.width = 0 ;
	hitContext.canvas.width = 1 ;
	return result ;
};

/**
 * 计算显示对象，以确定它是否与 obj 显示对象重叠或相交。
 * @param obj 碰撞对象
 * @param commParent 共同的父容器，如果不指定，则默认为Stage
 * @return 碰撞成功返回true
 */
DisplayObject.prototype.hitTestObject = function (obj , commParent , minAlpha)
{
	commParent = commParent?commParent:FlashCore.stage ;
	//判断矩形是否相交
	return this.getBounds(commParent).intersects(obj.getBounds(FlashCore.stage) ) ;
};

/**
 * 碰撞检测，像素级碰撞检测，<b>条件是没有进行过旋转和缩放</b>
 * @param obj
 * @param minAlpha 最小的alpha值，默认为 255
 * @returns 成功返回true
 */
DisplayObject.prototype.hitTestObjectPixels = function (obj , minAlpha)
{
	minAlpha = minAlpha?minAlpha:255 ; 
	var rect1 = this.getBounds(FlashCore.stage) ;
	var rect2 = obj.getBounds(FlashCore.stage) ;
	var result = rect1.intersects(rect2);
	if(!result) return false ;
	//像素精确检测
	result = false ;
	var hitContext = this._getPixelsHitTestContext ();
	try
	{	
		var intersection = rect1.intersection( rect2 ); //相交区域
		//画第一个对象
		hitContext.canvas.width = FlashCore.canvas.width;
		hitContext.canvas.height = FlashCore.canvas.height;
		this._draw( this._alpha ,  hitContext );
		var pixelData1 = hitContext.getImageData(intersection.x , intersection.y , intersection.width,intersection.height).data;
		//清除画布
		hitContext.canvas.width = 0 ;
		hitContext.canvas.width = FlashCore.canvas.height ;
		//画第二个对象
		obj._draw( obj._alpha ,  hitContext );
		var pixelData2 = hitContext.getImageData(intersection.x , intersection.y , intersection.width,intersection.height).data;
		//判断是否相交
		var i = 0;
		while(i < pixelData1.length)
		{
			if(pixelData1[i+3] >= minAlpha &&  pixelData2[i+3] >= minAlpha )
			{					
				result = true;
				break;
			}
			i += 4;
		}
	}catch(e){};

	hitContext.canvas.width = 0 ;
	hitContext.canvas.width = 1 ;
	return result;
};

/**
 * 释放资源
 */
DisplayObject.prototype.dispose = function()
{
	EventDispatcher.prototype.dispose.call(this);
	this._localModelMatrix = null ;
	this._worldModelMatrix = null ;
};
//==============私有方法=======================
/**
 * 更新此对象的矩阵
 */
DisplayObject.prototype._updateLocalMatrix = function()
{
	this._invalidateMatrix = false;
	this._localModelMatrix.identity();
	this._localModelMatrix.translate(this._x, this._y);
	this._localModelMatrix.rotate( this._rotation*Math.PI/180  );
	this._localModelMatrix.scale(this._scaleX, this._scaleY);
	this._localModelMatrix.translate(-this._pivotX, -this._pivotY );
};

/**
 * 更新世界矩阵
 */
DisplayObject.prototype._updateWorldMatrix = function()
{
	this._worldModelMatrix.identity();
	this._worldModelMatrix.concat(this._localModelMatrix);
	if(this._parent) {
		this._worldModelMatrix.concat(this._parent._worldModelMatrix);
	}
};

/**
 * 用于像素碰撞的Context
 * @returns
 */
DisplayObject.prototype._getPixelsHitTestContext = function()
{
	if( !DisplayObject._pixelsHitTestContext){
		DisplayObject._pixelsHitTestContext = document.createElement("canvas").getContext("2d");
		DisplayObject._pixelsHitTestContext.canvas.width =  1 ;
	}
	return DisplayObject._pixelsHitTestContext ;
};

/**
 * 渲染图形
 *@param globalAlpha 全局透明度
 *@param context 
 *@param parentMatrixchanged
 */
DisplayObject.prototype._render = function( globalAlpha , context , parentMatrixChanged )
{
	var myMatrixChanged = false;
	if(this._invalidateMatrix) {
		this._updateLocalMatrix();
		myMatrixChanged = true;
	}
	if(parentMatrixChanged || myMatrixChanged) {
		this._updateWorldMatrix();
		myMatrixChanged = true;
	}
	
	globalAlpha*=this._alpha ;
	if(this.visible){
		this._draw(globalAlpha , context);
	}
};
/**
 * 游戏的主循环
 */
DisplayObject.prototype._gameLoop = function(globalAlpha , context , parentMatrixChanged)
{
	if(this.hasEventListener(Event.ENTER_FRAME))
		this.dispatchEvent( new Event(Event.ENTER_FRAME) );
	
	this._render( globalAlpha , context , parentMatrixChanged );
	
	if(this.hasEventListener(Event.EXIT_FRAME))
		this.dispatchEvent( new Event(Event.EXIT_FRAME)) ;
};
/**
 * 输出
 * @param globalAlpha 
 * @param context
 */
DisplayObject.prototype._draw =function( globalAlpha,context )
{
	//抽象方法，子类重写
};
/**
 * 从父亲容器中移除
 */
DisplayObject.prototype._removeFromParent = function( dispose )
{
	if (this._parent) this._parent.removeChild(this);
    if (dispose) this._dispose();
};

/**
 * 子元素抛出事件
 * @param event 事件
 */
DisplayObject.prototype._dispatchEventOnChildren = function(event)
{
	this.dispatchEvent(event); 
};